﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Collections;

using Wrapper;
using modele.impl;
using modele.interfaces;

namespace UI
{
    /**
     * \file FabriqueCarteVue.cs
     * \brief Classe gérant la création de la map
     * \author Alexandre Carteron et Charles Robin
     * \version 1.0
     * \date 13/12/2012
     * 
     * Classe gérant la création de la map
     */
    class FabriqueCarteVue
    {
        public static int tailleCasePixel = 50; /*!<Définit la taille d'une case en pixels*/
        public static List<Grid> lignes = new List<Grid>(); /*!<liste des lignes à afficher*/

        /**
         * \fn public static void creerCarte(Grid uiCarte, int tailleCarte, WrapperAlgo w)
         * \brief Crée le terrain 
         * 
         * Crée le terrain 
         * 
         * \param[in] uiCare Grid sur laquelle on affichera la carte
         * \param[in] tailleCarte entier qui définit la taille de la carte
         * \param[in] WrapperAlgo qui définit la forme de la carte
         *
         */
        public static void creerCarte(Grid uiCarte, int tailleCarte, WrapperAlgo w)
        {
            //Grid g = MainWindow.INSTANCE.getCarte();
            uiCarte.Height = tailleCasePixel * tailleCarte;
            uiCarte.Width = tailleCasePixel * tailleCarte;
            //uiCarte.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(tailleCasePixel, GridUnitType.Pixel) });
            for (int i = 0; i < tailleCarte; i++)
                uiCarte.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(tailleCasePixel, GridUnitType.Pixel) });
            
            uiCarte.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(tailleCasePixel*tailleCarte, GridUnitType.Pixel) });

            for (int i = 0; i < tailleCarte; i++)
            {
                Grid g = new Grid();
                for (int j = 0; j < tailleCarte; j++)
                    g.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(tailleCasePixel, GridUnitType.Pixel) }); 
                g.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(tailleCasePixel, GridUnitType.Pixel) });

                g.Width = tailleCasePixel * tailleCarte;
                g.Height = tailleCasePixel;
                lignes.Add(g);
                Grid.SetColumn(g, 1);
                Grid.SetRow(g, i);
                uiCarte.Children.Add(g);
            }

            for (int i = 0; i < tailleCarte; i++)
            {
                for (int j = 0; j < tailleCarte; j++)
                {
                    int caseInfos = w.getCase(i, j);
                    
                    // Decorateur
                    Boolean decorated = false; 
                    Rectangle decorateur = (new Rectangle());
                    //addHandlers(decorateur);
                    decorateur.Fill = brushFactory.get((caseInfos>>15)<<15);
                    if (decorateur.Fill != null)
                    {
                        decorateur.Width = tailleCasePixel;
                        decorateur.Height = tailleCasePixel;

                        Grid.SetColumn(decorateur, i);
                        Grid.SetRow(decorateur, 1);
                        decorated = true;
                    }

                    // Terrain
                    Rectangle terrain = (new Rectangle());
                    //addHandlers(terrain);
                    Brush b = brushFactory.get((caseInfos<<15)>>15);
                    terrain.Fill = b;

                    terrain.Width = tailleCasePixel;
                    terrain.Height = tailleCasePixel;
                    Grid.SetColumn(terrain, i);
                    Grid.SetRow(terrain, 1);

                    // Ajout 
                    lignes[j].Children.Add(terrain);
                    if (decorated)
                        lignes[j].Children.Add(decorateur);
                }
            }            
        }

        /**
         * \fn public static void addHandlers(UIElement uie, int ligne)
         * \brief Ajoute les handlers souris à l'élément reçu en argument
         * 
         * Ajoute les handlers à l'élément reçu en argument
         * 
         * \param[in] uie UIElement sur lequel on rajoute les handlers souris
         * \param[in] ligne entier qui indique les coordonnées verticales de l'élément
         *
         */
        public static void addHandlers(UIElement uie, int ligne)
        {
            uie.MouseLeftButtonDown += new MouseButtonEventHandler((object sender, MouseButtonEventArgs e) =>
            {
                clicGauche(Grid.GetColumn(uie), ligne);
                  
                 e.Handled = true;
            });


            uie.MouseRightButtonDown += new MouseButtonEventHandler((object sender, MouseButtonEventArgs e) =>
            {
                clicDroit(Grid.GetColumn(uie), ligne);

                e.Handled = true;
            });
        }

        static List<MouseButtonEventHandler> leftHandlers = new List<MouseButtonEventHandler>();
        static List<MouseButtonEventHandler> rightHandlers = new List<MouseButtonEventHandler>();
        public static void addHandlersSuggestions(UIElement uie, int ligne, int num)
        {
            if (leftHandlers.Count <= num)
                leftHandlers.Add(new MouseButtonEventHandler((object sender, MouseButtonEventArgs e) =>
            {
                clicGauche(Grid.GetColumn(uie), ligne);

                e.Handled = true;
            }));
            else
            {
                uie.MouseLeftButtonDown -= leftHandlers[num];
                leftHandlers[num] = new MouseButtonEventHandler((object sender, MouseButtonEventArgs e) =>
            {
                clicGauche(Grid.GetColumn(uie), ligne);

                e.Handled = true;
            });
            }
            uie.MouseLeftButtonDown += leftHandlers[num];

            if (rightHandlers.Count <= num)
                rightHandlers.Add(new MouseButtonEventHandler((object sender, MouseButtonEventArgs e) =>
                    {
                clicDroit(Grid.GetColumn(uie), ligne);

                e.Handled = true;
                    }));
            else
            {
                uie.MouseRightButtonDown -= rightHandlers[num];
                rightHandlers[num] = new MouseButtonEventHandler((object sender, MouseButtonEventArgs e) =>
                {
                    clicDroit(Grid.GetColumn(uie), ligne);

                    e.Handled = true;
                });
            }
            uie.MouseRightButtonDown += rightHandlers[num];

        }
        public static bool montrer = false; /*!<indique si on doit montrer les propositions de cases*/
        /**
         * \fn public static void clicGauche(int x, int y)
         * \brief Action effectuée lors d'un clic gauche
         * 
         * Action effectuée lors d'un clic gauche
         * 
         * \param[in] x entier coordonnées horizontales
         * \param[in] y entier coordonnées verticales
         *
         */
        public static void clicGauche(int x, int y)
        {

            JoueurImpl j = (JoueurImpl)JeuImpl.INSTANCE.joueurs[JeuImpl.INSTANCE.joueurCourant];
            Carte cj = JeuImpl.INSTANCE.carte;
            j.unitesSelectionnees = JeuImpl.INSTANCE.carte.getInfosCase(x, y).unites;
            j.curseurX = x;
            j.curseurY = y;
            if (j.aEnseignantSelec())
            {
                montrer = true;
            }
            else
            {
                montrer = false;
            }
            removeSelection();
            Grid.SetRow(MainWindow.INSTANCE.selectionRectangle, 1);
            Grid.SetColumn(MainWindow.INSTANCE.selectionRectangle, x);
            lignes[y].Children.Add(MainWindow.INSTANCE.selectionRectangle);
            MainWindow.INSTANCE.selectionRectangle.Visibility = System.Windows.Visibility.Visible;
            TabManager.makeDocks(x, y);
            MainWindow.INSTANCE.gestionTour.mettreAJourCarte();
        }

        /**
         * \fn public static void removeSelection()
         * \brief Enlève le rectangle de sélection de l'élément parent
         * 
         * Enlève le rectangle de sélection de l'élément parent
         * 
         */
        public static void removeSelection()
        {
            ((Grid)MainWindow.INSTANCE.selectionRectangle.Parent).Children.Remove(MainWindow.INSTANCE.selectionRectangle);
        }

        /**
         * \fn public static void clicDroit(int x, int y)
         * \brief Action effectuée lors d'un clic droit
         * 
         * Action effectuée lors d'un clic droit
         * 
         * \param[in] x entier coordonnées horizontales
         * \param[in] y entier coordonnées verticales
         */
        public static void clicDroit(int x, int y)
        {

            Joueur j = JeuImpl.INSTANCE.joueurs[JeuImpl.INSTANCE.joueurCourant];
            j.curseurX = x;
            j.curseurY = y;
            List<Unite> listeArrivee = JeuImpl.INSTANCE.carte.getInfosCase(x, y).unites;
            /*List<Unite> unitesSelectionnees = new List<Unite>();
            foreach(Unite u in  j.unitesSelectionnees)
                unitesSelectionnees.Add(u);*/
            if (Keyboard.IsKeyDown(Key.LeftCtrl) && MainWindow.INSTANCE.menuGauche.SelectedIndex != -1)
            {
                Unite u = j.unitesSelectionnees[MainWindow.INSTANCE.menuGauche.SelectedIndex];
                j.unitesSelectionnees = new List<Unite>();
                j.unitesSelectionnees.Add(u);
            }//*/
            if (j.unitesSelectionnees != null && j.unitesSelectionnees.Count > 0 && j.unitesSelectionnees[0].joueur == j && (listeArrivee.Count == 0 || listeArrivee[0].joueur == j))
            {
                int nb = j.unitesSelectionnees.Count;
                for (int i = 0; i < nb; i++)
                {
                    Unite u = j.unitesSelectionnees[0];
                    j.unitesSelectionnees.Remove(u);
                    j.unitesSelectionnees.Add(u);
                    j.unitesSelectionnees[0].deplacer(x, y);
                }
                if (JeuImpl.INSTANCE.carte.getInfosCase(x, y).unites.Count != 0)
                    j.unitesSelectionnees = JeuImpl.INSTANCE.carte.getInfosCase(x, y).unites;
            }
            if (j.unitesSelectionnees != null && j.unitesSelectionnees.Count > 0 && j.unitesSelectionnees[0].joueur == j && (listeArrivee.Count > 0 && listeArrivee[0].joueur != j))
            {
                int nb = j.unitesSelectionnees.Count;
                for (int i = 0; i < nb; i++)
                {
                    Unite u = j.unitesSelectionnees[i];
                    if (u is EtudiantImpl)
                        ((EtudiantImpl)j.unitesSelectionnees[i]).attaquer(x, y);
                    if (!j.unitesSelectionnees.Contains(u)) // si l'unité meurt
                    {
                        i--;
                        nb--;
                    }
                }
                if (JeuImpl.INSTANCE.carte.getInfosCase(x, y).unites.Count != 0)
                    j.unitesSelectionnees = JeuImpl.INSTANCE.carte.getInfosCase(x, y).unites;
            }
            if (j.aEnseignantSelec() && j.unitesSelectionnees.Count > 0 && j.unitesSelectionnees[0].x == x && j.unitesSelectionnees[0].y == y)
            {
                montrer = true;
            }
            else
            {
                montrer = false;
            }
            removeSelection();
            Grid.SetRow(MainWindow.INSTANCE.selectionRectangle, 1);
            Grid.SetColumn(MainWindow.INSTANCE.selectionRectangle, x);
            lignes[y].Children.Add(MainWindow.INSTANCE.selectionRectangle);
            MainWindow.INSTANCE.selectionRectangle.Visibility = System.Windows.Visibility.Visible;
            TabManager.makeDocks(x, y);
            MainWindow.INSTANCE.gestionTour.mettreAJourCarte();

        }
    }
}
